package us.feng.tinyspring.beans.factory.xml;

import us.feng.tinyspring.beans.BeanDefinition;
import us.feng.tinyspring.beans.factory.support.AbstractBeanDefinitionReader;
import us.feng.tinyspring.beans.factory.support.BeanDefinitionRegistry;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import us.feng.tinyspring.io.Resource;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	
	private DocumentBuilderFactory documentBuildFactory = DocumentBuilderFactory.newInstance();
	
	private static final Logger LOGGER=LoggerFactory.getLogger(XmlBeanDefinitionReader.class);

	public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
		super(registry);
	}

	public void registerBeanDefinitions(Document doc, Resource resource) {
		Element root=doc.getDocumentElement();
		BeanDefinitionParserDelegate delegate=new BeanDefinitionParserDelegate(this);
		
		parseBeanDefinitions(root, delegate);
	}

	public void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		NodeList nl=root.getChildNodes();
		for(int i=0;i<nl.getLength();i++){
			Node node = nl.item(i);
			if(node instanceof Element){
				Element ele=(Element) node;
				if(BeanDefinitionParserDelegate.BEAN_ELEMENT.equals(ele.getNodeName())){
					String beanName=ele.getAttribute(BeanDefinitionParserDelegate.ID_ATTRIBUTE);
					BeanDefinition beanDefinition=delegate.parseBeanDefinitionElement(ele,beanName);
					
					LOGGER.debug("Parse Bean:[{}]",beanName);
					
					getRegistry().registerBeanDefinition(beanName, beanDefinition);
				}
			}
		}
	}

	@Override
	public int loadBeanDefinitions(Resource resource) {
		InputStream is=null;
		try {
			int countBefore=getRegistry().getBeanDefinitionCount();
			
			DocumentBuilder docBuilder = documentBuildFactory.newDocumentBuilder();
			is = resource.getInputStream();
			Document doc = docBuilder.parse(is);
			registerBeanDefinitions(doc, resource);
			
			return getRegistry().getBeanDefinitionCount()-countBefore;
			
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(null!=is){
				try {
					is.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return 0;
	}

}
